﻿using System;
using System.IO;
using System.Text.RegularExpressions;

namespace ExtractItAll.Core
{
  public enum ArchiveFormat
  {
    Unknown,
    Rar,
    SevenZip,
    Zip,
  }

  public class ArchiveItem
  {
    public ArchiveItem(string fileName)
    {
      FileInfo = new FileInfo(fileName);

      if (IsRarFile()) return;
      if (Is7z()) return;
      if (IsZip()) return;

      Format = ArchiveFormat.Unknown;
    }

    public string FileName
    {
      get
      {
        if (FileInfo == null)
          return null;

        return FileInfo.FullName;
      }
    }

    public FileInfo FileInfo { get; set; }


    public ArchiveFormat Format { get; private set; }
    public bool IsSubVolume { get; private set; }
    public string VolumeFormat { get; private set; }
    public int VolumeCounter { get; private set; }

    public static string GetRegEx(ArchiveFormat format)
    {
      switch (format)
      {
        case ArchiveFormat.Rar:
          return @"^(?<name>.+?)\.((?<a>part(?<num>\d+)\.rar)|(?<b>r(?<num>\d{2}))|rar)$";

        case ArchiveFormat.SevenZip:
          //return @"^(?<name>.+?)\.7z$";
          return @"^(?<name>.+?)\.((?<a>7z\.(?<num>\d{3}))|7z)$";

        case ArchiveFormat.Zip:
          return @"^(?<name>.+?)\.zip$";
          //return @"^(?<name>.+?)\.((?<a>zip\.(?<num>\d{3}))|zip)$";

        default:
          return null;
      }
    }

    public static Match GetMatch(ArchiveFormat format, string filename)
    {
      string regEx = GetRegEx(format);

      Match match = new Regex(regEx, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase)
        .Match(filename);

      return match;
    }

    private Match GetMatch(ArchiveFormat format)
    {
      return GetMatch(format, FileName);
    }

    private bool IsRarFile()
    {
      Match match = GetMatch(ArchiveFormat.Rar);

      if (match.Success)
      {
        Format = ArchiveFormat.Rar;

        if (match.Groups["a"].Success)
        {
          VolumeFormat = match.Groups["name"].Value + ".part{0}.rar";
          VolumeCounter = Convert.ToInt32(match.Groups["num"].Value);

          IsSubVolume = VolumeCounter != 1;
        }
        else if (match.Groups["b"].Success)
        {
          VolumeFormat = match.Groups["name"].Value + ".r{0:00}";
          VolumeCounter = Convert.ToInt32(match.Groups["num"].Value);

          IsSubVolume = true;
        }
        else
        {
          VolumeFormat = null;
          VolumeCounter = -1;

          IsSubVolume = false;
        }

        return true;
      }

      return false;
    }

    private bool Is7z()
    {
      Match match = GetMatch(ArchiveFormat.SevenZip);

      if (match.Success)
      {
        Format = ArchiveFormat.SevenZip;

        if (match.Groups["a"].Success)
        {
          VolumeFormat = match.Groups["name"].Value + ".7z.{0:000}";
          VolumeCounter = Convert.ToInt32(match.Groups["num"].Value);

          IsSubVolume = VolumeCounter != 1;
        }
        else
        {
          VolumeFormat = null;
          VolumeCounter = -1;

          IsSubVolume = false;
        }

        return true;
      }

      return false;
    }

    private bool IsZip()
    {
      Match match = GetMatch(ArchiveFormat.Zip);

      if (match.Success)
      {
        Format = ArchiveFormat.Zip;

        if (match.Groups["a"].Success)
        {
          VolumeFormat = match.Groups["name"].Value + ".zip.{0:000}";
          VolumeCounter = Convert.ToInt32(match.Groups["num"].Value);

          IsSubVolume = VolumeCounter != 1;
        }
        else
        {
          VolumeFormat = null;
          VolumeCounter = -1;

          IsSubVolume = false;
        }

        return true;
      }

      return false;
    }
  }
}